;

const DEBUG = false;

const boardCanvas = document.querySelector('#board');
let info;

/**
 * 棋盘的列数
 */
const COLS = 15;
/**
 * 棋盘的行数
 */
const ROWS = 15;
/**
 * 棋盘
 */
const board = [];
const BOARD_MARGIN = 20;
const BOARD_BORDER = 40;
const boardContext = boardCanvas ? boardCanvas.getContext("2d") : null;
const BOARD_COLOR = ["", "black", "white"];
const POINT_SIZE = 10;
const CENTER_POINT_SIZE = 5;

let initial = false;

let currentColor = 1;

let gameover = false;

function isValid(board, point, color) {
    const rows = board.length;
    const cols = board[0].length;
    const [x, y] = point;
    return x >= 0 && x < cols && y >= 0 && y < rows && board[y][x] === color;
}

function createIsWin(p1Movement, p2Movement) {
    return function (board, point, color) {
        let count = 1;
        let p1 = p1Movement(point);
        let p2 = p2Movement(point);
        while (1) {
            let p1IsValid = false;
            let p2IsValid = false;
            if (/* p1有效 */ isValid(board, p1, color)) {
                count++;
                p1IsValid = true;
                p1 = p1Movement(p1);
            }
            if (/* p2有效 */ isValid(board, p2, color)) {
                count++;
                p2IsValid = true;
                p2 = p2Movement(p2);
            }
            if (count >= 5) {
                return true;
            }
            if (!p1IsValid && !p2IsValid) {
                return false;
            }
        }
    }
}

const isWinHorizontal = createIsWin(([x, y]) => [x + 1, y], ([x, y]) => [x - 1, y]);
const isWinVertical = createIsWin(([x, y]) => [x, y + 1], ([x, y]) => [x, y - 1]);
const isWinDiagonal = createIsWin(([x, y]) => [x + 1, y + 1], ([x, y]) => [x - 1, y - 1]);
const isWinBackDiagonal = createIsWin(([x, y]) => [x + 1, y - 1], ([x, y]) => [x - 1, y + 1]);

/**
 * Check if the given point is a win for the given color
 * @param board - checkerboard
 * @param point - the point
 * @param color - the color
 * @returns {boolean} - true if the point is a win for the given color
 */
function isWin(board, point, color) {
    return isWinHorizontal(board, point, color) ||
        isWinVertical(board, point, color) ||
        isWinDiagonal(board, point, color) ||
        isWinBackDiagonal(board, point, color);
}

/**
 * Convert coordinates to chessboard array positions
 * @param point - coordinates
 * @param boarder - chessboard size
 * @returns {point} - array positions
 */
function pointTransform(point, boarder) {
    let [x, y] = point;
    if (DEBUG) {
        console.log(x, y, boarder);
    }
    x = Math.max(0, x);
    y = Math.max(0, y);
    let tempX = x / boarder;
    let tempY = y / boarder;
    if (DEBUG) {
        console.log(tempX, tempY, Math.round(tempX), Math.round(tempY));
    }
    return [Math.round(tempX), Math.round(tempY)];
}

function _initStyle() {
    boardCanvas.width = COLS * BOARD_MARGIN * 2;
    boardCanvas.height = ROWS * BOARD_MARGIN * 2;
    boardCanvas.style = "border: 2px solid red;margin: 50px";
    boardCanvas.style.marginTop = "0px";
    info = document.createElement("div");
    info.style = "text-align: center;margin: 10px 50px";
    info.style.width = boardCanvas.width + 'px';
    boardCanvas.parentElement.insertBefore(info, boardCanvas);
}

/**
 * 初始化棋盘
 */
function initBoard() {
    if (!boardCanvas || !boardContext) {
        console.log("initBoard failed, canvas with ID board required and support canvas context");
        alert("初始化失败, 棋盘canvas元素ID必须为board, 且浏览器支持canvas!");
        return;
    }
    if (initial) {
        return;
    }
    initial = true;
    _initStyle();
    for (let y = 0; y < COLS; y++) {
        board.push([]);
        for (let x = 0; x < ROWS; x++) {
            board[y].push(0);
        }
    }
    drawBoard();

    refershInfo();
    boardCanvas.onclick = function (e) {
        if (gameover) {
            alert("游戏已经结束, 重置棋盘");
            reset();
            return;
        }
        console.log(e);
        const offsetX = e.offsetX - BOARD_MARGIN;
        const offsetY = e.offsetY - BOARD_MARGIN;
        const point = pointTransform([offsetX, offsetY], BOARD_BORDER);
        console.log(point);
        if (!isValidAction(point, board)) {
            alert("无效位置, 请重新选择位置");
            return;
        }
        if (isWin(board, point, currentColor)) {
            console.log(board, point, currentColor);
            gameover = true;
            const msg = "恭喜" + (currentColor === 1 ? "黑棋" : "白棋") + "赢了";
            board[point[1]][point[0]] = currentColor === 1 ? 1 : 2;
            currentColor = currentColor === 1 ? 2 : 1;
            refreshBoard();
            refershInfo(msg);
            alert(msg);
            return;
        }
        board[point[1]][point[0]] = currentColor === 1 ? 1 : 2;
        currentColor = currentColor === 1 ? 2 : 1;
        refreshBoard();
    };
}

/**
 * 是否是有效动作
 * @param {point} point check point
 * @param {board} board - the board
 * @returns {boolean} true if valid
 */
function isValidAction(point, board) {
    const [x, y] = point;
    console.log(x, y, board);
    return board[y][x] == 0;
}

/**
 * 绘制棋盘
 */
function drawBoard() {
    for (let y = 0; y < COLS; y++) {
        for (let x = 0; x < ROWS; x++) {
            if (y < COLS - 1 && x < ROWS - 1) {
                boardContext.strokeStyle = "black";
                boardContext.strokeRect(x * BOARD_BORDER + BOARD_MARGIN, y * BOARD_BORDER + BOARD_MARGIN, BOARD_BORDER, BOARD_BORDER);//绘制格子
                if (x === y && x === Math.floor(COLS / 2)) {
                    // 绘制中心点
                    if (DEBUG) {
                        console.log(x, "中心点");
                    }
                    boardContext.fillStyle = "black";
                    boardContext.arc(x * BOARD_BORDER + BOARD_MARGIN, y * BOARD_BORDER + BOARD_MARGIN, CENTER_POINT_SIZE, 0, 2 * Math.PI, false);
                    boardContext.fill();
                }
            }
        }
    }
}

/**
 * 绘制棋子
 * @param {CanvasRenderingContext2D} context
 * @param {*} point
 * @param {*} color
 */
function drawPoint(context, point, color) {
    const [x, y] = point;
    context.fillStyle = color;
    context.beginPath();
    context.arc(x * BOARD_BORDER + BOARD_MARGIN, y * BOARD_BORDER + BOARD_MARGIN, POINT_SIZE, 0, 2 * Math.PI, false);
    context.fill();
    if (DEBUG) {
        console.log(point, color);
    }
}

/**
 * 刷新棋盘
 */
function refreshBoard() {
    boardContext.clearRect(0, 0, boardCanvas.width, boardCanvas.height);
    drawBoard();
    for (let y = 0; y < COLS; y++) {
        for (let x = 0; x < ROWS; x++) {
            if (board[y][x] === 1) {
                drawPoint(boardContext, [x, y], BOARD_COLOR[1]);
            } else if (board[y][x] === 2) {
                drawPoint(boardContext, [x, y], BOARD_COLOR[2]);
            }
        }
    }
    refershInfo();
    if (DEBUG) {
        console.log('刷新棋盘');
        console.log('board=', board);
    }
}

/**
 * 更新棋盘信息
 */
function refershInfo(msg) {
    if (info) {
        info.innerText = !msg ? '当前为' + (currentColor === 1 ? '黑子' : '白子') : msg;
    }
}

/**
 * 重置棋盘
 */
function reset() {
    if (DEBUG) {
        console.log('重置棋盘');
    }
    gameover = false;
    currentColor = 1;
    // 重置棋盘
    board.forEach((row, y) => {
        row.forEach((col, x) => {
            board[y][x] = 0;
        });
    });
    boardContext.reset();
    refreshBoard();
    refershInfo();
}

export { initBoard, reset }